Add tests exercising the registry source
authorAlex Crichton <alex@alexcrichton.com>
Tue, 9 Sep 2014 05:26:14 +0000 (22:26 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 16 Sep 2014 19:05:21 +0000 (12:05 -0700)
src/cargo/sources/registry.rs
src/cargo/util/config.rs
tests/fixtures/bar-0.0.1.tar.gz [new file with mode: 0644]
tests/fixtures/foo-0.0.1.tar.gz [new file with mode: 0644]
tests/fixtures/notyet-0.0.1.tar.gz [new file with mode: 0644]
tests/support/mod.rs
tests/test_cargo_registry.rs [new file with mode: 0644]
tests/tests.rs

index f3e34fe1a1c1a50a7f7374ae5e3f3a153d46aa2d..1a46c97be0d4c8391c6a0ac21d22a262b1d781de 100644 (file)
@@ -72,14 +72,6 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
         url.as_slice().to_url().map_err(human)
     }
 
-    /// Translates the HTTP url of the registry to the git URL
-    fn git_url(&self) -> Url {
-        let mut url = self.source_id.get_url().clone();
-        url.path_mut().unwrap().push("git".to_string());
-        url.path_mut().unwrap().push("index".to_string());
-        url
-    }
-
     /// Decode the configuration stored within the registry.
     ///
     /// This requires that the index has been at least checked out.
@@ -103,7 +95,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
 
         try!(fs::mkdir_recursive(&self.checkout_path, io::UserDir));
         let _ = fs::rmdir_recursive(&self.checkout_path);
-        let url = self.git_url().to_string();
+        let url = self.source_id.get_url().to_string();
         let repo = try!(git2::Repository::init(&self.checkout_path));
         Ok(repo)
     }
@@ -115,7 +107,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
     /// then ready for inspection.
     ///
     /// No action is taken if the package is already downloaded.
-    fn download_package(&mut self, pkg: &PackageId, url: Url)
+    fn download_package(&mut self, pkg: &PackageId, url: &Url)
                         -> CargoResult<Path> {
         let dst = self.cache_path.join(url.path().unwrap().last().unwrap()
                                           .as_slice());
@@ -132,7 +124,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
         };
         // TODO: don't download into memory
         let resp = try!(handle.get(url.to_string()).exec());
-        if resp.get_code() != 200 {
+        if resp.get_code() != 200 && resp.get_code() != 0 {
             return Err(internal(format!("Failed to get 200 reponse from {}\n{}",
                                         url, resp)))
         }
@@ -235,7 +227,7 @@ impl<'a, 'b> Source for RegistrySource<'a, 'b> {
         let repo = try!(self.open());
 
         // git fetch origin
-        let url = self.git_url().to_string();
+        let url = self.source_id.get_url().to_string();
         let refspec = "refs/heads/*:refs/remotes/origin/*";
         let mut remote = try!(repo.remote_create_anonymous(url.as_slice(),
                                                            refspec));
@@ -265,8 +257,9 @@ impl<'a, 'b> Source for RegistrySource<'a, 'b> {
             url.path_mut().unwrap().push(format!("{}-{}.tar.gz",
                                                  package.get_name(),
                                                  package.get_version()));
-            let path = try!(self.download_package(package, url).chain_error(|| {
-                internal(format!("Failed to download package `{}`", package))
+            let path = try!(self.download_package(package, &url).chain_error(|| {
+                internal(format!("Failed to download package `{}` from {}",
+                                 package, url))
             }));
             let path = try!(self.unpack_package(package, path).chain_error(|| {
                 internal(format!("Failed to unpack package `{}`", package))
index a6c85574ed11dba591abdc43295c6447a63ad1c8..de382e12c47a6eb9746e79dcb45b708d6ae4c944 100644 (file)
@@ -156,8 +156,8 @@ impl ConfigValue {
 
     fn merge(&mut self, from: ConfigValue) -> CargoResult<()> {
         match (self, from) {
-            (me @ &String(..), from @ String(..)) => *me = from,
-            (me @ &Boolean(..), from @ Boolean(..)) => *me = from,
+            (&String(..), String(..)) |
+            (&Boolean(..), Boolean(..)) => {}
             (&List(ref mut old), List(ref mut new)) => {
                 let new = mem::replace(new, Vec::new());
                 old.extend(new.move_iter());
diff --git a/tests/fixtures/bar-0.0.1.tar.gz b/tests/fixtures/bar-0.0.1.tar.gz
new file mode 100644 (file)
index 0000000..55b2f5a
Binary files /dev/null and b/tests/fixtures/bar-0.0.1.tar.gz differ
diff --git a/tests/fixtures/foo-0.0.1.tar.gz b/tests/fixtures/foo-0.0.1.tar.gz
new file mode 100644 (file)
index 0000000..bf1fc95
Binary files /dev/null and b/tests/fixtures/foo-0.0.1.tar.gz differ
diff --git a/tests/fixtures/notyet-0.0.1.tar.gz b/tests/fixtures/notyet-0.0.1.tar.gz
new file mode 100644 (file)
index 0000000..5b8ae93
Binary files /dev/null and b/tests/fixtures/notyet-0.0.1.tar.gz differ
index e257a28d67a1a2ee1834a2f953de6bdfbf7e4d47..8d177ef266a3fec8d1b7bc0e3eef40a80df0fa23 100644 (file)
@@ -284,12 +284,12 @@ impl Execs {
 
     fn match_stdout(&self, actual: &ProcessOutput) -> ham::MatchResult {
         self.match_std(self.expect_stdout.as_ref(), actual.output.as_slice(),
-        "stdout", actual.error.as_slice())
+                       "stdout", actual.error.as_slice())
     }
 
     fn match_stderr(&self, actual: &ProcessOutput) -> ham::MatchResult {
         self.match_std(self.expect_stderr.as_ref(), actual.error.as_slice(),
-        "stderr", actual.output.as_slice())
+                       "stderr", actual.output.as_slice())
     }
 
     fn match_std(&self, expected: Option<&String>, actual: &[u8],
@@ -505,9 +505,10 @@ pub fn path2url(p: Path) -> Url {
     Url::from_file_path(&p).unwrap()
 }
 
-pub static RUNNING:   &'static str = "     Running";
-pub static COMPILING: &'static str = "   Compiling";
-pub static FRESH:     &'static str = "       Fresh";
-pub static UPDATING:  &'static str = "    Updating";
-pub static DOCTEST:   &'static str = "   Doc-tests";
-pub static PACKAGING: &'static str = "   Packaging";
+pub static RUNNING:     &'static str = "     Running";
+pub static COMPILING:   &'static str = "   Compiling";
+pub static FRESH:       &'static str = "       Fresh";
+pub static UPDATING:    &'static str = "    Updating";
+pub static DOCTEST:     &'static str = "   Doc-tests";
+pub static PACKAGING:   &'static str = "   Packaging";
+pub static DOWNLOADING: &'static str = " Downloading";
diff --git a/tests/test_cargo_registry.rs b/tests/test_cargo_registry.rs
new file mode 100644 (file)
index 0000000..6c40e41
--- /dev/null
@@ -0,0 +1,239 @@
+use std::io::{mod, fs, File};
+use url::Url;
+use git2;
+use serialize::hex::ToHex;
+
+use support::{ResultTest, project, execs, cargo_dir};
+use support::{UPDATING, DOWNLOADING, COMPILING};
+use support::paths;
+use cargo::util::Sha256;
+
+use hamcrest::assert_that;
+
+fn registry_path() -> Path { paths::root().join("registry") }
+fn registry() -> Url { Url::from_file_path(&registry_path()).unwrap() }
+fn dl_path() -> Path { paths::root().join("dl") }
+fn dl_url() -> Url { Url::from_file_path(&dl_path()).unwrap() }
+
+fn cksum(s: &[u8]) -> String {
+    let mut sha = Sha256::new();
+    sha.update(s);
+    sha.final().to_hex()
+}
+
+fn setup() {
+    let config = paths::root().join(".cargo/config");
+    fs::mkdir_recursive(&config.dir_path(), io::UserDir).assert();
+    File::create(&config).write_str(format!(r#"
+        [registry]
+            host = "{reg}"
+            token = "api-token"
+    "#, reg = registry()).as_slice()).assert();
+
+    fs::mkdir(&registry_path(), io::UserDir).assert();
+
+    // Init a new registry
+    let repo = git2::Repository::init(&registry_path()).unwrap();
+    let mut config = repo.config().unwrap();
+    config.set_str("user.name", "name").unwrap();
+    config.set_str("user.email", "email").unwrap();
+    let mut index = repo.index().unwrap();
+
+    // Prepare the "to download" artifacts
+    let foo = include_bin!("fixtures/foo-0.0.1.tar.gz");
+    let bar = include_bin!("fixtures/bar-0.0.1.tar.gz");
+    let notyet = include_bin!("fixtures/notyet-0.0.1.tar.gz");
+    let foo_cksum = dl("pkg/foo/foo-0.0.1.tar.gz", foo);
+    let bar_cksum = dl("pkg/bar/bar-0.0.1.tar.gz", bar);
+    dl("pkg/bad-cksum/bad-cksum-0.0.1.tar.gz", foo);
+    let notyet = dl("pkg/notyet/notyet-0.0.1.tar.gz", notyet);
+
+    // Prepare the registry's git repo
+    file(&mut index, "config.json", format!(r#"
+        {{"dl_url":"{}"}}
+    "#, dl_url()).as_slice());
+    file(&mut index, "fo/oX/foo",
+         format!(r#"{{"name":"foo","vers":"0.0.1","deps":[],"cksum":"{}"}}"#,
+                 foo_cksum).as_slice());
+    file(&mut index, "ba/rX/bar",
+         format!(r#"{{"name":"bar","vers":"0.0.1","deps":["foo|>=0.0.0"],"cksum":"{}"}}"#,
+                 bar_cksum).as_slice());
+    file(&mut index, "ba/d-/bad-cksum",
+         format!(r#"{{"name":"bad-cksum","vers":"0.0.1","deps":[],"cksum":"{}"}}"#,
+                 bar_cksum).as_slice());
+    file(&mut index, "no/ty/notyet",
+         format!(r#"{{"name":"notyet","vers":"0.0.1","deps":[],"cksum":"{}"}}"#,
+                 notyet).as_slice());
+    index.remove_path(&Path::new("no/ty/notyet")).unwrap();
+
+    // Commit!
+    index.write().unwrap();
+    let id = index.write_tree().unwrap();
+    let tree = git2::Tree::lookup(&repo, id).unwrap();
+    let sig = git2::Signature::default(&repo).unwrap();
+    git2::Commit::new(&repo, Some("HEAD"), &sig, &sig,
+                      "Initial commit", &tree, []).unwrap();
+
+    fn file(index: &mut git2::Index, path: &str, contents: &str) {
+        let dst = index.path().unwrap().dir_path().dir_path().join(path);
+        fs::mkdir_recursive(&dst.dir_path(), io::UserDir).assert();
+        File::create(&dst).write_str(contents).unwrap();
+        index.add_path(&Path::new(path)).unwrap();
+    }
+
+    fn dl(path: &str, contents: &[u8]) -> String {
+        let dst = dl_path().join(path);
+        fs::mkdir_recursive(&dst.dir_path(), io::UserDir).assert();
+        File::create(&dst).write(contents).unwrap();
+        cksum(contents)
+    }
+}
+
+test!(simple {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            foo = ">= 0.0.0"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(0).with_stdout(format!("\
+{updating} registry `{reg}`
+{downloading} foo v0.0.1 (the package registry)
+{compiling} foo v0.0.1 (the package registry)
+{compiling} foo v0.0.1 ({dir})
+",
+        updating = UPDATING,
+        downloading = DOWNLOADING,
+        compiling = COMPILING,
+        dir = p.url(),
+        reg = registry()).as_slice()));
+})
+
+test!(deps {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            bar = ">= 0.0.0"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(0).with_stdout(format!("\
+{updating} registry `{reg}`
+{downloading} [..] v0.0.1 (the package registry)
+{downloading} [..] v0.0.1 (the package registry)
+{compiling} foo v0.0.1 (the package registry)
+{compiling} bar v0.0.1 (the package registry)
+{compiling} foo v0.0.1 ({dir})
+",
+        updating = UPDATING,
+        downloading = DOWNLOADING,
+        compiling = COMPILING,
+        dir = p.url(),
+        reg = registry()).as_slice()));
+})
+
+test!(nonexistent {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            nonexistent = ">= 0.0.0"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+No package named `nonexistent` found (required by `foo`).
+Location searched: the package registry
+Version required: >= 0.0.0
+"));
+})
+
+test!(bad_cksum {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            bad-cksum = ">= 0.0.0"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+
+    assert_that(p.cargo_process("build").arg("-v"),
+                execs().with_status(101).with_stderr("\
+Unable to get packages from source
+
+Caused by:
+  Failed to download package `bad-cksum v0.0.1 (the package registry)` from [..]
+
+Caused by:
+  Failed to verify the checksum of `bad-cksum v0.0.1 (the package registry)`
+"));
+})
+
+test!(update_registry {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            notyet = ">= 0.0.0"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(101).with_stderr("\
+No package named `notyet` found (required by `foo`).
+Location searched: the package registry
+Version required: >= 0.0.0
+"));
+
+    // Add the package and commit
+    let repo = git2::Repository::open(&registry_path()).unwrap();
+    let mut index = repo.index().unwrap();
+    index.add_path(&Path::new("no/ty/notyet")).unwrap();
+    let id = index.write_tree().unwrap();
+    let tree = git2::Tree::lookup(&repo, id).unwrap();
+    let sig = git2::Signature::default(&repo).unwrap();
+    let parent = git2::Reference::name_to_id(&repo, "refs/heads/master").unwrap();
+    let parent = git2::Commit::lookup(&repo, parent).unwrap();
+    git2::Commit::new(&repo, Some("HEAD"), &sig, &sig,
+                      "Another commit", &tree,
+                      [&parent]).unwrap();
+
+    assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+                execs().with_status(0).with_stdout(format!("\
+{updating} registry `{reg}`
+{downloading} notyet v0.0.1 (the package registry)
+{compiling} notyet v0.0.1 (the package registry)
+{compiling} foo v0.0.1 ({dir})
+",
+        updating = UPDATING,
+        downloading = DOWNLOADING,
+        compiling = COMPILING,
+        dir = p.url(),
+        reg = registry()).as_slice()));
+})
index cc96d9ae1ecc1c6dd84045c57db6ce042a99b936..56133c420cdfb0b00091701e77b44f3253b1e1b5 100644 (file)
@@ -4,6 +4,7 @@
 extern crate cargo;
 extern crate git2;
 extern crate hamcrest;
+extern crate serialize;
 extern crate term;
 extern crate url;
 
@@ -41,3 +42,4 @@ mod test_cargo_generate_lockfile;
 mod test_cargo_profiles;
 mod test_cargo_package;
 mod test_cargo_build_auth;
+mod test_cargo_registry;